package com.tcm.item.service.category;

import com.base.core.utils.R;
import com.base.genid.generator.UidGenerator;
import com.base.core.tree.TreeParser;
import com.base.core.dozer.DozerConvert;
import com.tcm.item.domain.constant.CategoryConstant;
import com.tcm.item.domain.enums.BusinessCodeEnum;
import com.tcm.item.domain.dto.CategoryDTO;
import com.tcm.item.domain.entity.DrugsCategory;
import com.tcm.item.domain.vo.DrugsCategoryVO;
import com.tcm.item.mapper.DrugsCategoryMapper;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;

import java.time.LocalDateTime;
import java.util.List;

@DubboService(version = "0.0.1-alpha", timeout = 3000, retries = 3)
public class CategoryServiceImpl implements CategoryService {

    @Autowired
    private DrugsCategoryMapper drugsCategoryMapper;

    private final TreeParser<DrugsCategoryVO> parser = new TreeParser<>();

    @DubboReference(version = "0.0.1-beta", group = "cached-uid", retries = 3, timeout = 3000, check = false)
    private UidGenerator uidGenerator;

    /**
     * 获得一级子分类
     * @param parentId 父id
     * @return
     * @throws Exception
     */
    @Override
    public List<DrugsCategoryVO> listSubCategory(Long parentId) throws Exception {
        return listSubCategory(parentId, false);
    }

    /**
     * 查询分类数据
     * @param id
     * @return
     */
    @Override
    public DrugsCategoryVO findCategoryById(Long id){
        DrugsCategory drugsCategory = drugsCategoryMapper.findCategoryById(id);
        return DozerConvert.copyProperties(drugsCategory, DrugsCategoryVO.class);
    }

    /**
     * 获得所有分类
     * @return
     * @throws Exception
     */
    @Override
    public List<DrugsCategoryVO> listAllCategory() throws Exception{
        List<DrugsCategory> drugsCategory = drugsCategoryMapper.listCategory();
        return DozerConvert.copyList(drugsCategory, DrugsCategoryVO.class);
    }

    /**
     * 转换为树形结构
     *
     * @return
     * @throws Exception
     */
    @Override
    public List<DrugsCategoryVO> listToTree() throws Exception {
        return parser.treeList(0L,listAllCategory());
    }

    /**
     * 递归查询子类
     * @param parentId 父类id
     * @param recursive
     * @return
     * @throws Exception
     */
    @Override
    public List<DrugsCategoryVO> listSubCategory(Long parentId, boolean recursive) throws Exception {
        if(!recursive){
            List<DrugsCategory> itemCategories = drugsCategoryMapper.findChildList(parentId);
            return DozerConvert.copyList(itemCategories, DrugsCategoryVO.class);
        }
        List<DrugsCategoryVO> listItemCategoryVo = DozerConvert.copyList(listAllCategory(), DrugsCategoryVO.class);
        return parser.findChildNodes(listItemCategoryVo, parentId);
    }

    /**
     * 加载所有父分类
     * @param categoryId
     * @return
     * @throws Exception
     */
    @Override
    public List<DrugsCategoryVO> loadParents(Long categoryId) throws Exception {
        List<DrugsCategoryVO> listItemCategoryVo = DozerConvert.copyList(listAllCategory(), DrugsCategoryVO.class);
        return parser.findParentNodes(listItemCategoryVo, categoryId);
    }

    /**
     * 获取当前类别的所有父类别ID
     * @param categoryId
     * @return
     * @throws Exception
     */
    @Override
    public List<Long> listParentIds(Long categoryId) throws Exception {
        List<DrugsCategoryVO> listItemCategoryVo = DozerConvert.copyList(listAllCategory(), DrugsCategoryVO.class);
        return parser.findParentIds(listItemCategoryVo, categoryId);
    }

    /**
     * 获得当前类别所有子类别ID
     * @param categoryId
     * @return
     * @throws Exception
     */
    @Override
    public List<Long> listChildIds(Long categoryId) throws Exception {
        List<DrugsCategoryVO> listItemCategoryVo = DozerConvert.copyList(listAllCategory(), DrugsCategoryVO.class);
        return parser.findChildNodeIds(listItemCategoryVo, categoryId);
    }

    /**
     * 验证分类有效性
     *
     * @param categoryId
     * @return
     */
    @Override
    public DrugsCategoryVO validCategory(Long categoryId) {
        // 校验分类是否存在
        DrugsCategory drugsCategory = drugsCategoryMapper.findCategoryById(categoryId);
        if (drugsCategory == null) {
            R.throwFail(BusinessCodeEnum.PRODUCT_CATEGORY_NOT_EXISTS);
        }
        //禁用的商品分类不可用
        if (CategoryConstant.STATUS_DISABLE.equals(drugsCategory.getStatus())) {
            R.throwFail(BusinessCodeEnum.PRODUCT_CATEGORY_MUST_ENABLE);
        }
        //验证是否叶子分类
        List<DrugsCategory> childCategory = drugsCategoryMapper.findChildList(drugsCategory.getId());
        if(childCategory != null && childCategory.size() > 0){
            R.throwFail(BusinessCodeEnum.PRODUCT_CATEGORY_PARENT_CAN_NOT_BE_LEAF);
        }
        // 返回结果
        return DozerConvert.copyProperties(drugsCategory, DrugsCategoryVO.class);
    }

    /**
     * 创建分类
     *
     * @param categoryDto
     * @return
     */
    @Override
    public int createCategory(CategoryDTO categoryDto){
        //设置深度
        setCategoryLevel(categoryDto);
        // 保存到数据库
        DrugsCategory drugsCategory = DozerConvert.copyProperties(categoryDto, DrugsCategory.class);
        drugsCategory.setId(uidGenerator.getUID());
        drugsCategory.setCreateTime(LocalDateTime.now());
        drugsCategory.setUpdateTime(LocalDateTime.now());
        return drugsCategoryMapper.insert(drugsCategory);
    }

    /**
     * 更新分类
     *
     * @param categoryDto
     * @return
     */
    @Override
    public int updateCategory(CategoryDTO categoryDto) {
        // 校验不能设置自己为父分类
        if (categoryDto.getId().equals(categoryDto.getParentId())) {
            R.throwFail(BusinessCodeEnum.PRODUCT_CATEGORY_PARENT_NOT_SELF);
        }
        // 校验父分类是否存在
        if (!categoryDto.getParentId().equals(0L)
                && drugsCategoryMapper.findCategoryById(categoryDto.getParentId()) == null) {
            R.throwFail(BusinessCodeEnum.PRODUCT_CATEGORY_PARENT_NOT_EXISTS);
        }
        //设置深度
        setCategoryLevel(categoryDto);
        // 更新到数据库
        DrugsCategory updateCategory = DozerConvert.copyProperties(categoryDto, DrugsCategory.class);
        updateCategory.setUpdateTime(LocalDateTime.now());
        return drugsCategoryMapper.update(updateCategory);
        // TODO 操作日志
    }

    /**
     * 根据分类的parentId设置分类的level
     */
    private void setCategoryLevel(CategoryDTO categoryDto) {
        //没有父分类时为一级分类
        if (categoryDto.getParentId() == 0) {
            categoryDto.setLevel(new Byte("1"));
        } else {
            //有父分类时选择根据父分类level设置
            DrugsCategory parentCategory = drugsCategoryMapper.findCategoryById(categoryDto.getParentId());
            if (parentCategory != null) {
                categoryDto.setLevel((byte) (parentCategory.getLevel() + 1));
            } else {
                categoryDto.setLevel(new Byte("1"));
            }
        }
    }

    /**
     * 删除分类
     *
     * @param categoryId
     * @return
     */
    @Override
    public int deleteCategory(Long categoryId) {
        // 校验分类是否存在
       DrugsCategory drugsCategory = drugsCategoryMapper.findCategoryById(categoryId);
        if (drugsCategory == null) {
            R.throwFail(BusinessCodeEnum.PRODUCT_CATEGORY_NOT_EXISTS);
        }

        // TODO 是否需要判断下该分类下是否有商品
        // 是否有子类
        List<DrugsCategory> itemCategories = drugsCategoryMapper.findChildList(categoryId);
        if(!itemCategories.isEmpty()){
            R.throwFail(BusinessCodeEnum.PRODUCT_CHILD_CATEGORY_EXISTS);
        }
        // 标记删除商品分类
        return drugsCategoryMapper.deleteForLogic(categoryId);
        // TODO 操作日志
    }


}
